#include "codeVisitor.h"
#include "ast.h"

#include <fstream>


map<string, varsAttributes> varsMapping;
int mapCnt=5;

int labelCnt=0;
int extraCnt=0;

void CodeVisitor::visit(Node *n){
}
void CodeVisitor::visit(Expr *n){
	


}
void CodeVisitor::visit(ExprList *n){
}
void CodeVisitor::visit(Dim *n){
}
void CodeVisitor::visit(Atom *n){
}
void CodeVisitor::visit(IntConst *n){
}
void CodeVisitor::visit(RealConst *n){
}
void CodeVisitor::visit(True *n){
}
void CodeVisitor::visit(False *n){
}
void CodeVisitor::visit(Var *n){
}
void CodeVisitor::visit(ArrayRef *n){
}
void CodeVisitor::visit(RecordRef *n){
}
void CodeVisitor::visit(AddressRef *n){
}
void CodeVisitor::visit(Statement *n){
}
void CodeVisitor::visit(Type *n){
}
void CodeVisitor::visit(NewStatement *n){
}
void CodeVisitor::visit(WriteStrStatement *n){
}
void CodeVisitor::visit(WriteVarStatement *n){
}
void CodeVisitor::visit(ProcedureStatement *n){
}
void CodeVisitor::visit(Case *n){

	n->stat_list_->accept(this);
}
void CodeVisitor::visit(CaseList *n){
		int tmp2=0;

		output<<"L"<<labelCnt<<"\n";
		tmp2=labelCnt;
		labelCnt++;
		n->case_->accept(this);
		output<<"ujp L"<<extraCnt<<"\n";
		if (n->case_list_!=NULL)
		{
			n->case_list_->accept(this);
		}
		
		output<<"ujp L"<<tmp2<<"\n"; //tmp holds the ixj value
}
void CodeVisitor::visit(CaseStatement *n){

    int tmpXtraCnt;

    n->exp_->accept(this);
	output<<"neg i\n";
 	output<<"ixj L"<<labelCnt<<"\n";
 	tmpXtraCnt=extraCnt;
    extraCnt=labelCnt;
	labelCnt++;
	
	if(n->case_list_!=NULL)
	{
		n->case_list_->accept(this);
	}
	
	output<<"L"<<extraCnt<<"\n";
	extraCnt=tmpXtraCnt;
}
void CodeVisitor::visit(LoopStatement *n){
	//a while statement consists of the condition which is an expression and
	//the statement, therefore the exp_ calling codeR and the statement callig 
	//itself
	
	//Each time a label is used it has to be incremented and kept so that
	//1) No one else will use that same label and 2) I can go back to that same
	//label when I need to, for this I will use tmp1 and tmp2
	
    int tmp1=0; //tmp1 will hold the label of entry to the while loop
	int tmp2=0; //tmp2 holds fjp label which comes after the condition check
    
	output<<"L"<<labelCnt<<"\n";  
	tmp1=labelCnt;
	labelCnt++;
	
	n->exp_->accept(codeRight);
    output<<"fjp L"<<labelCnt<<"\n";
	tmp2=labelCnt;
   	labelCnt++;

	n->stat_list_->accept(this);
	output<<"ujp L"<<tmp1<<"\n";
    output<<"L"<<tmp2<<"\n";
}

void CodeVisitor::visit(ConditionalStatement *n){
	
	int tmpCnt=0;
	n->exp_->accept(codeRight);
	output<<"fjp L"<<labelCnt<<"\n";
	tmpCnt=labelCnt;
	labelCnt++;
	
	n->stat_list_if_->accept(this);
	
	if(n->stat_list_else_!=NULL)
	{
		output<<"ujp L"<<labelCnt<<"\n";//relevant only if there is else
		output<<"L"<<tmpCnt<<"\n";//label is saved in tmpCnt so I have its value
							      //after returning from the recursive if_stat_
		tmpCnt=labelCnt;//the labelCnt is reserved so as to put it at the end of the 
						//IF ELSE block, this closes the ujp L(i)
		labelCnt++;
		n->stat_list_else_->accept(this);
	}
	output<<"L"<<tmpCnt<<"\n";
}

void CodeVisitor::visit(Assign *n){
	
	n->var_->accept(codeLeft); 
	n->exp_->accept(codeRight);
	output<<"sto i\n";
}
void CodeVisitor::visit(StatementList *n){

	n->stat_->accept(this);
	if(n->stat_list_!=NULL)
	{
		n->stat_list_->accept(this);
	}
}
void CodeVisitor::visit(Declaration *n){
}
void CodeVisitor::visit(VariableDeclaration *n){
	//varsMapping[*n->name_]=mapCnt;//move to visit(ArrayType) as no longer cnt++ but calc of dimensions 
    n->type_->accept(this);/////////////***/
	mapCnt++;
}
void CodeVisitor::visit(RecordList *n){
}
void CodeVisitor::visit(SimpleType *n){
}
void CodeVisitor::visit(IdeType *n){

    output<<"ldo i "<<varsMapping[*n->name_].address<<"\n";
}
void CodeVisitor::visit(ArrayType *n){
}
void CodeVisitor::visit(RecordType *n){
}
void CodeVisitor::visit(AddressType *n){
}
void CodeVisitor::visit(Parameter *n){
}
void CodeVisitor::visit(ByReferenceParameter *n){
}
void CodeVisitor::visit(ParameterList *n){
}
void CodeVisitor::visit(FunctionDeclaration *n){
}
void CodeVisitor::visit(ProcedureDeclaration *n){
}
void CodeVisitor::visit(DeclarationList *n){
    
	if(n->decl_list_ !=NULL)
	{
		n->decl_list_->accept(this);
	}
	n->decl_->accept(this); 
}
void CodeVisitor::visit(Block *n){
	
	n->decl_list_->accept(this);  

	n->stat_seq_->accept(this);
}
void CodeVisitor::visit(Program *n){ 
		
	n->block_->accept(this);	
	output<<"stp\n";
}

/**
 OutputFile_ is the file that !you! (the students),
 write your output to;
 */
CodeVisitor::CodeVisitor(ostream& OutputFile_):
Visitor(OutputFile_)
{
	
}

CodeVisitor::~CodeVisitor()
{
}

